package com.gitee.secretopen.plugin;


import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.gitee.secretopen.plugin.config.SecretPluginConfig;
import com.gitee.secretopen.plugin.model.PluginModel;
import com.gitee.secretopen.plugin.model.PluginModelObserver;
import com.gitee.secretopen.plugin.observer.Observer;
import com.gitee.secretopen.plugin.util.JsonUtil;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 　@description: 插件工厂，生产内置插件和外部插件
 * 　@author secret
 * 　@date 2021/1/28 13:56
 *
 */
public class SecretPluginFactory {

    /**
     * 插件集合
     */
    private static Map<String,Object> pluginMap;
    /**
     * 插件信息列表
     */
    private static List<PluginModel> pluginModelList;
    /**
     * 内置插件包
     */
    private String pluginPackage;
    /**
     * 外部插件路径
     */
    private File pluginPath;

    /**
     * 获取插件初始化配置
     */
    private static SecretPluginConfig config=SecretPluginConfig.getInstance();

    /**
     * 只加载内置插件
     * @param pluginPackage
     */
    public SecretPluginFactory(String pluginPackage){
        pluginMap=new HashMap<>();
        pluginModelList=new ArrayList<>();
        this.pluginPackage=pluginPackage;
        loadPlugins();
    }

    public SecretPluginFactory(File pluginPath){
        pluginMap=new HashMap<>();
        pluginModelList=new ArrayList<>();
        this.pluginPath=pluginPath;
        loadPlugins();
    }


    public SecretPluginFactory(String pluginPackage,File pluginPath){
        pluginMap=new HashMap<>();
        pluginModelList=new ArrayList<>();
        this.pluginPackage=pluginPackage;
        this.pluginPath=pluginPath;
        loadPlugins();
    }

    /**
     * 加载内置和外部插件
     */
    private void loadPlugins(){
        Observer pluginModelObserver=new PluginModelObserver();
        SecretPluginClassLoader classLoader = null;
        //判断加载哪种插件
        if(StrUtil.isNotEmpty(pluginPackage) && pluginPath!=null) { //内置和外置
            classLoader = new SecretPluginClassLoader(pluginPackage, pluginPath);
        } else if(StrUtil.isNotEmpty(pluginPackage)){ //内置
            classLoader = new SecretPluginClassLoader(pluginPackage);
        } else if(pluginPath!=null){ //外置
            classLoader = new SecretPluginClassLoader(pluginPath);
        }
        List<Object> pluginList = classLoader.getPluginList();
        //读取json文件
        File pluginJsonFile=null;
        List<PluginModel> pluginModelJsonList=null;
        if(config.isUseFile()) {
            String jsonPath=config.getPluginJsonPath();
            //如果不是绝对路径,转化为绝对路径
            if(!FileUtil.isAbsolutePath(jsonPath)){
                jsonPath=new File(jsonPath).getAbsolutePath();
            }
            pluginJsonFile = FileUtil.touch(jsonPath);
            pluginModelJsonList = JsonUtil.jsonToList(pluginJsonFile, PluginModel.class);
        }
        for(Object plugin:pluginList){
            SecretPluginInterface pluginInterface=(SecretPluginInterface) plugin;
            String className=pluginInterface.getClass().getCanonicalName();//获取简单类名称，包含包名
            //存入map
            pluginMap.put(className,pluginInterface);
            //存入插件信息列表，默认所有插件全部打开
            PluginModel pluginModel=new PluginModel();
            pluginModel.setClassName(className);
            pluginModel.setName(pluginInterface.getPluginName());
            pluginModel.setHasSetup(pluginInterface.hasSetup());
            pluginModel.setEnabled(true);
            //如果启用json文件，则注册观察者
            if(config.isUseFile()) {
                pluginModel.registerObserver(pluginModelObserver);
            }
            pluginModelList.add(pluginModel);
        }
        //如果配置文件不为空，比较加载的插件和配置文件中的插件，设置是否启用，并将pluginModuleList转为json覆盖配置文件
        if(config.isUseFile()) {
            outPluginJson(pluginModelJsonList,pluginJsonFile);
        }
        //插件启动
        pluginStart();
    }


    /**
     * 输出json文件
     * @param pluginModelJsonList
     * @param pluginJsonFile
     */
    private void outPluginJson(List<PluginModel> pluginModelJsonList,File pluginJsonFile){
        //如果配置文件不为空，比较加载的插件和配置文件中的插件，设置是否启用，并将pluginModuleList转为json覆盖配置文件
        if (pluginModelJsonList != null && pluginModelJsonList.size() != 0) {
            pluginModelJsonList.forEach(jsonObj -> {
                //先获取map中是否存在该插件，如果不存在，减少不必要的二层遍历
                if (pluginMap.get(jsonObj.getClassName()) == null) {
                    return;
                }
                pluginModelList.forEach(pluginModel -> {
                    if (pluginModel.getClassName().equals(jsonObj.getClassName())) {//如果className一样，则认为是同一插件
                        pluginModel.setEnabled(jsonObj.isEnabled());
                    }
                });
            });
        }
        //覆盖插件文件
        String newPluginJsonStr=JsonUtil.objectToJsonFormat(pluginModelList);
        cn.hutool.core.io.file.FileWriter fileWriter=new cn.hutool.core.io.file.FileWriter(pluginJsonFile);
        fileWriter.write(newPluginJsonStr);
    }

    /**
     * 启动插件
     */
    private void pluginStart(){
        pluginModelList.forEach(pluginModel->{
            if(pluginModel.isEnabled()){
                SecretPluginInterface plugin=(SecretPluginInterface) pluginMap.get(pluginModel.getClassName());
                plugin.initialize();
            }
        });
    }

    public static Map<String, Object> getPluginMap() {
        return pluginMap;
    }

    public static List<PluginModel> getPluginModelList() {
        return pluginModelList;
    }
}
